#ifndef _GLOBAL_ARRAY_H_
#define _GLOBAL_ARRAY_H_
#endif


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "mpi.h"
#include "uohashtable.h"

#define MAX_NODES 256
#define MSG_NEW_ARRAY 10

#define CMD_NEW_ARRAY    11000
#define CMD_PUT_ELEMENT  14000
#define CMD_PUT_ARRAY    17000
#define CMD_GET_ELEMENT  15000
#define CMD_GET_ARRAY    18000
#define CMD_FREE_ARRAY   12000
#define CMD_FINALIZE     21000
#define CMD_FINALIZE2    22000

#define CMD_STORE_ELEMENT   25000
#define CMD_STORE_ARRAY     35000

#define MODE_DEFAULT_BALANCE 1000
#define MODE_RANDOM_BALANCE 1001
#define MODE_ROTATE_BALANCE 1002
#define MODE_LEAST_BALANCE 1003


typedef struct
{
    int type;  // newarray: TYPE_INT='int', TYPE_LONG='long', TYPE_DOUBLE= 'double'
    int dim ;  // newarray: 1 or 2 or 3
    int length;// putarray, getarray
    int loc;   // : the node where the variable is stored
    int offset;
    double value;  // put/get element: 1 element value
    int index[3];  // put/get element, put/get array :index for 1d,2d,3D matrix
    int size[3];   // newarray:specify size of each dimension
    char name[16]; // all:array name
    double value_array[20]; // put/get array
	
} Msg;


void uo_init(int argc, char **argv);
void uo_new_array(char *name, int type, int *size, int dimension);
void uo_put_element(char *name, int *index, void *value, int type);
void uo_put_array(char *name, int start, void *buffer, int buffer_start, int size, int type);
void uo_get_element(char *name, int *index, void *value,int type);
void uo_get_array(char *name, int start, void *buffer, int buffer_start, int size, int type);
void uo_free_array(char *name);
void uo_finalize();
void uo_recv(Msg* msg, int size, MPI_Datatype msgtype, int source, int tag, MPI_Comm comm, MPI_Status* status);
void uo_send(Msg* msg, int size, MPI_Datatype msgtype, int source, int tag, MPI_Comm comm);
void uo_load_balacne(int index);
void *listener();

void storeElement(Msg recv_msg);
void sentElement(Msg recv_msg,int to, int tag);


int cmd_to_tag(int cmd);
int tag_to_cmd(int tag);
